package com.xjgz.aio.socket.buffer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.function.Consumer;

/**
 * DirectBuffer 内存清理工具类
 * 提供多种清理策略,按优先级依次尝试:
 * 1. JDK 9+ 标准 Cleaner API (推荐)
 * 2. JDK 9+ Unsafe.invokeCleaner (反射)
 * 3. JDK 8 DirectBuffer.cleaner().clean() (反射)
 */
class DirectBufferCleaner {

    private static Consumer<ByteBuffer> cleaner;

    private static boolean directSupported = true;

    private static String cleanerStrategy = "unknown";

    static {
        int javaMajorVersion = getJavaMajorVersion();

        // 策略1: 优先尝试 JDK 9+ 标准 Cleaner API
        if (javaMajorVersion >= 9 && tryJdk9CleanerAPI()) {
            cleanerStrategy = "JDK9+ Cleaner API";
        }
        // 策略2: 尝试 Unsafe.invokeCleaner (JDK 9+)
        else if (javaMajorVersion >= 9 && tryUnsafeInvokeCleaner()) {
            cleanerStrategy = "Unsafe.invokeCleaner";
        }
        // 策略3: 尝试 DirectBuffer.cleaner().clean() (JDK 8)
        else if (tryDirectBufferCleaner()) {
            cleanerStrategy = "DirectBuffer.cleaner";
        }
        // 所有策略失败
        else {
            directSupported = false;
            cleanerStrategy = "none (fallback to GC)";
            System.err.println("[WARNING] DirectBuffer cleaner not available, relying on GC");
        }

        System.out.println("[INFO] DirectBuffer cleaner strategy: " + cleanerStrategy);
    }

    /**
     * 策略1: 使用 JDK 9+ 标准 Cleaner API
     * 优点: 标准API,无需反射,性能最好
     */
    private static boolean tryJdk9CleanerAPI() {
        try {
            // 检查是否存在 jdk.internal.ref.Cleaner (JDK 9+)
            Class<?> cleanerClass = Class.forName("jdk.internal.ref.Cleaner");
            Method cleanMethod = cleanerClass.getMethod("clean", ByteBuffer.class);

            cleaner = buffer -> {
                try {
                    cleanMethod.invoke(null, buffer);
                } catch (Exception e) {
                    throw new RuntimeException("Failed to clean direct buffer via Cleaner API", e);
                }
            };
            return true;
        } catch (Throwable e) {
            return false;
        }
    }

    /**
     * 策略2: 使用 Unsafe.invokeCleaner (JDK 9+)
     * 优点: JDK 9+ 官方推荐的内部方法
     */
    private static boolean tryUnsafeInvokeCleaner() {
        try {
            Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
            Field theUnsafeField = unsafeClass.getDeclaredField("theUnsafe");
            theUnsafeField.setAccessible(true);
            Object unsafe = theUnsafeField.get(null);
            Method invokeCleaner = unsafeClass.getMethod("invokeCleaner", ByteBuffer.class);

            cleaner = buffer -> {
                try {
                    invokeCleaner.invoke(unsafe, buffer);
                } catch (Exception e) {
                    throw new RuntimeException("Failed to clean direct buffer via Unsafe", e);
                }
            };
            return true;
        } catch (Throwable e) {
            return false;
        }
    }

    /**
     * 策略3: 使用 DirectBuffer.cleaner().clean() (JDK 8)
     * 优点: JDK 8 兼容
     */
    private static boolean tryDirectBufferCleaner() {
        try {
            Class<?> directBufferClass = Class.forName("sun.nio.ch.DirectBuffer");
            Method cleanerMethod = directBufferClass.getMethod("cleaner");
            Method cleanMethod = Class.forName("sun.misc.Cleaner").getMethod("clean");

            cleaner = buffer -> {
                try {
                    Object cleaner = cleanerMethod.invoke(buffer);
                    if (cleaner != null) {
                        cleanMethod.invoke(cleaner);
                    }
                } catch (Exception e) {
                    throw new RuntimeException("Failed to clean direct buffer via DirectBuffer", e);
                }
            };
            return true;
        } catch (Throwable e) {
            return false;
        }
    }

    public static boolean isDirectSupported() {
        return directSupported;
    }

    public static String getCleanerStrategy() {
        return cleanerStrategy;
    }

    /**
     * 清理 DirectBuffer 占用的堆外内存
     *
     * @param buffer 需要清理的 ByteBuffer (必须是 DirectBuffer)
     */
    public static void clean(ByteBuffer buffer) {
        if (buffer == null || !buffer.isDirect()) {
            return;
        }

        if (cleaner != null) {
            cleaner.accept(buffer);
        } else {
            // 降级到 GC 处理
            buffer = null;
            System.gc();
        }
    }

    private static int getJavaMajorVersion() {
        String version = System.getProperty("java.specification.version");
        // 处理类似"1.8.0_301"和"9+"两种版本格式
        return version.startsWith("1.") ? Integer.parseInt(version.split("\\.")[1])
                : Integer.parseInt(version.split("\\.")[0]);
    }
}
